package cn.com.dhcc.ddi.task.service.load;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.ddi.datasource.vo.DataSourceConfVo;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cn.com.dhcc.app.core.exception.CompressException;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.NiceException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.compresshandler.CompressService;
import cn.com.dhcc.app.core.handler.compresshandler.CompressServiceFactory;
import cn.com.dhcc.app.core.handler.compresshandler.CompressStatic;
import cn.com.dhcc.app.core.handler.threadpoolhandler.ThreadPool;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.tag.CommonStaticCode;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.CM;
import cn.com.dhcc.app.pub.core.consts.DdiProperties;
import cn.com.dhcc.app.pub.core.handler.FileRecvAnalyzeHandler;
import cn.com.dhcc.app.pub.core.handler.IAnalyzeCallBack;
import cn.com.dhcc.app.pub.core.tag.staticcode.StaticCode;
import cn.com.dhcc.ddi.datamapping.dao.DataMappingDao;
import cn.com.dhcc.ddi.datamapping.vo.DataMapping;
import cn.com.dhcc.ddi.datasource.dao.DataSourceDao;
import cn.com.dhcc.ddi.datasource.service.DataSourceDBService;
import cn.com.dhcc.ddi.datasource.vo.DataSourceVo;
import cn.com.dhcc.ddi.task.dao.TaskActiveLogDao;
import cn.com.dhcc.ddi.task.dao.TaskExecuteLogDao;
import cn.com.dhcc.ddi.task.service.ChangeVo;
import cn.com.dhcc.ddi.task.service.ChangeVo.ColPro;
import cn.com.dhcc.ddi.task.service.ChangeVo.ColType;
import cn.com.dhcc.ddi.task.service.ChangeVo.ConvertInfo;
import cn.com.dhcc.ddi.task.service.ChangeVo.RowPro;
import cn.com.dhcc.ddi.task.service.DbTypeConvertUtils;
import cn.com.dhcc.ddi.task.service.Result;
import cn.com.dhcc.ddi.task.service.TaskExecuteLogService;
import cn.com.dhcc.ddi.task.vo.Task;
import cn.com.dhcc.ddi.task.vo.TaskActiveLog;
import cn.com.dhcc.ddi.task.vo.TaskExecuteLog;

/**
 * 数据库数据加载抽象类
 * @日期：2016/11/18 9:16
 * @作者：张洪涛
 * @版权所有：东华软件
 * @版本：1.0
 */
@Service
public abstract class LDataSourceDBAbstract implements LDataSourceInterface{
    private static Logger logger = Log.getLogger(Log.LOGTYPE.DDI);
    private static Logger load_logger = Log.getLogger("LOAD_LOG");
    private static SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");//时间戳
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期
    public static String datebase_system="SYSDATE";//是否为系统时间标志
    @Autowired
    private TaskExecuteLogDao taskExecuteLogDao;
    @Autowired
    private DataMappingDao dmDao;
    @Autowired
    private DataSourceDao dsDao;
    @Autowired
    private ExecuteChangeDbDataImpl executeChangeDbDataImpl;
    @Autowired
    private TaskActiveLogDao taskActiveLogDao;
    @Autowired
    DataSourceDBService dataSourceDBService;

    /**
     * 解压文件
     * @param needCompressFile 需要解压的文件
     * @param outPath 解压后的文件路径
     * @return true 解压成功  false 解压失败
     */
    private static String unCompress(File needCompressFile, String outPath){
        //获取解压缩处理的service
        CompressService compressService = CompressServiceFactory.createCompressService(CompressStatic.COMPRESS_ALGORITHM.JAVA_GZIP);
        String after = null;
        try {
            String fileName = needCompressFile.getName();
            if (StringUtils.isEmpty(fileName)){
                return null;
            }
            after = outPath + File.separator+fileName.substring(0,fileName.indexOf(".tdata"));//解压缩后文件名
            after = compressService.uncompress(needCompressFile, after, true);
        } catch (CompressException e) {
            logger.error("[unCompress]解压文件发生异常", e);
        }
        return after;
    }

    /**
     * 加载
     * @param task
     * @param taskLogId
     * @param dateString 数据库当前时间
     * @return
     * @throws ServiceException
     */
    public Result load(Task task, String taskLogId, String dateString) throws ServiceException {
        try {
            Result result = new Result();
            result.setTaskLogId(taskLogId);
            logger.info("开始执行load...");
            //记录加载环节日志
            TaskExecuteLog loadLog = new TaskExecuteLog();
            loadLog.setId(UUIDGenerator.getUUID());
            loadLog.setTaskId(task.getId());
            loadLog.setLinkType(TaskExecuteLog.LINK_TYPE.LOAD.getCode());
            loadLog.setLinkStartTime(new Date());
            loadLog.setMtime(new Date());
            loadLog.setGroupId(taskLogId);

            taskExecuteLogDao.insert(loadLog);
            result.setLinkLogId(loadLog.getId());
            //获取抽取日志
            TaskExecuteLog transformtLog = taskExecuteLogDao.getTransformtLog(taskLogId);
            if (transformtLog.getLogStatus() == null || transformtLog.getLogStatus().equalsIgnoreCase(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus()) || transformtLog.getLogStatus().equalsIgnoreCase("")){
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("映射数据失败");
                if(transformtLog.getLogStatus().equalsIgnoreCase("") || transformtLog.getLogStatus() == null){
                    transformtLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                    transformtLog.setLinkEndTime(new Date());
                    taskExecuteLogDao.update(transformtLog);
                }
                return result;
            }
            if(transformtLog.getTotal() == 0 ){
                String msg = "本次任务没有交换数据.";
                result.setStatus(CommonStaticCode.SUCCESSFAIL.SUCCESS.getStatus());
                result.setMsg(msg);
                loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.SUCCESS.getStatus());
                loadLog.setLinkEndTime(new Date());
                loadLog.setLinkSummary(msg);
                loadLog.setTotal(0);
                taskExecuteLogDao.update(loadLog);
                return result;
            }
            //先复制新的文件到指定目录中，操作复制后的数据文件，防止读取文件过程中错误，导致文件失效
            String inputPath = transformtLog.getLinkDataFilePath();
            String outPath = DdiProperties.APP_UPLOAD_FILEDATA_PATH + File.separator + "load" + File.separator + task.getId() + File.separator + taskLogId;
            if (StringUtils.isEmpty(inputPath)){
                logger.error("[load]获取到数据文件路径失败。路径为空。");
                //如果查询出的文件目录为空，则不进行复制，只更新数据库状态，不进行后续操作
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("[load]获取到数据文件路径失败。路径为空。");
                return result;
            }
            String outDataPath = outPath + File.separator + inputPath.substring(inputPath.lastIndexOf("\\") + 1);
            File inputFile = new File(inputPath);
            File outdir = new File(outPath);
            if(!outdir.exists()){
                outdir.mkdir();
            }
            File outFile = new File(outDataPath);
            logger.info("[load]开始复制文件..." + inputPath);
            try {
                FileUtils.copyFile(inputFile, outFile);
            } catch (IOException e) {
                logger.error("[load]copy " + inputFile + " 发生异常", e);
//                updateExchDataLog(exchData.getId(), StaticCode.EXCH_DATA_STATUS.WAIT.getCode());
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("[load]copy " + inputFile + " 发生异常");
                return result;
            }
            logger.info("[load]" + outFile + "文件复制完成...开始解压缩...");
            String unCompFile = unCompress(outFile, outPath);
            //解压失败，则状态更改为“待执行”
            if (StringUtils.isEmpty(unCompFile)){
                logger.error("[load]执行解压文件 失败，更改状态为\"待执行\"。");
//                updateExchDataLog(exchData.getId(), StaticCode.EXCH_DATA_STATUS.WAIT.getCode());
                //删除掉复制的文件
                if (outFile.exists()){
                    logger.error("[load]解压文件失败，删除源文件。");
                    outFile.delete();
                }
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("[load]执行解压文件 失败");
                return result;
            }
            logger.info("[load]" + outFile + "文件解压完成...解压后的文件为：" + unCompFile);
            //解压完成后，进行文件解析，并进行入库操作(根据配置的数据源信息)
            loadLog.setLinkDataFilePath(unCompFile);
            taskExecuteLogDao.update(loadLog);
            result = parseXml(task,loadLog.getId(), unCompFile, transformtLog.getTotal(),dateString);
            logger.info("执行完毕load...");
            loadLog = taskExecuteLogDao.get(loadLog.getId());
            if (result.getStatus()== null || result.getStatus().equals(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus())){
                loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                loadLog.setLogMsg("加载数据失败");
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("加载数据失败");
            }
            loadLog.setLinkEndTime(new Date());
            taskExecuteLogDao.update(loadLog);
            return result;
        } catch (DaoException e) {
           throw new ServiceException(e);
        }
    }

    /**
     * 解析数据文件
     * @param task
     * @param loadLog
     * @param unCompFile
     * @param sendSqlNumber
     */
    private Result parseXml(final Task task, final String loadLogid, String unCompFile, final long transformTotal, final String databaseSystime) {
        final ExecutorService exec = Executors.newFixedThreadPool(DdiProperties.APP_EXECUTION_MAXQUERYNUM);
        final TaskExecuteLogService taskExecuteLogService = CM.getBean(TaskExecuteLogService.class);
        try {
            TaskExecuteLog loadLog  = taskExecuteLogDao.get(loadLogid);
            DataMapping dm = dmDao.get(task.getMpId());
            try{
                final File uncFile = new File(unCompFile);
                logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"]，获取DataSourceVo");
                //获取目的数据源
                final DataSourceVo destDs = dsDao.get(dm.getDestDsId());
                DataSourceConfVo dsConfVo = JsonUtil.toObject(destDs.getConf(),DataSourceConfVo.class);
                destDs.setDataSourceConfVo(dsConfVo);
                final TaskActiveLog log = taskActiveLogDao.getByTaskId(task.getId());
                boolean isOk = dataSourceDBService.dsStatusOk(destDs);
                if(isOk){
                    logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],开始解析了。。。。");
                    //查询当前线程池是否有这样的线程池，按照节点名字创建
                    Runnable run = new Runnable() {
                        public void run() {
                            SAXParserFactory factory = SAXParserFactory.newInstance();
                            try {
                                SAXParser parser = factory.newSAXParser();
                                parser.parse(uncFile, new DataFileHandler(FileRecvAnalyzeHandler.MAX_NUM, new IAnalyzeCallBack() {
                                    @Override
                                    public void proccess(ChangeVo vo) throws NiceException {
                                        load_logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],vo{"+vo+"}。");
                                        load_logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],loadLogid{"+loadLogid+"}。");
                                        try {
                                            log.setMtime(new Date());
                                            taskActiveLogDao.update(log);
                                        } catch (DaoException e) {
                                            load_logger.error("更新任务实时活动日志异常",e);
                                        }
                                        execute(destDs, vo, loadLogid,databaseSystime);
                                        if (vo.isOver()) {//如果文件解析完毕，删除该文件
                                            load_logger.info("[parseXml]更新t_ddi_task_log表id:" + loadLogid+",状态为：" + StaticCode.EXCH_DATA_STATUS.OVER.getCode());
                                            //更新交换日志状态信息
                                            //解析完成，通知
                                            load_logger.info("[recvTask]回调通知修改表id:" + loadLogid+",状态：" + CommonStaticCode.SUCCESSFAIL.SUCCESS.getStatus());
                                            boolean flag = uncFile.delete();
                                            load_logger.warn("数据文件["+uncFile.getAbsolutePath()+"]解析完毕，删除结果"+flag);
                                            try {
                                                TaskExecuteLog loadLog = taskExecuteLogService.get(loadLogid);
                                                if(loadLog.getTotal() == transformTotal) {
                                                    loadLog.setErrorNum(loadLog.getErrorNum() + (transformTotal - loadLog.getTotal()));
                                                    String linkSummary = "";
                                                    long total = loadLog.getTotal();
                                                    long insertCount = loadLog.getInsertNum();
                                                    long updateCount = loadLog.getUpdateNum();
                                                    long errorCount= loadLog.getErrorNum();
                                                    if(total > 0 ){
                                                        linkSummary = linkSummary + "数据加载结果,总数:"+total+" ";
                                                    }
                                                    if (insertCount>0) {
                                                        linkSummary = linkSummary+"新增:"+insertCount+" ";
                                                    }
                                                    if (updateCount>0) {
                                                        linkSummary = linkSummary+"更新:"+updateCount+" ";
                                                    }
                                                    if (errorCount>0) {
                                                        linkSummary = linkSummary+"失败:"+errorCount+".";
                                                    }
                                                    loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.SUCCESS.getStatus());
                                                    loadLog.setLogMsg("数据加载成功");
                                                    loadLog.setLinkSummary(linkSummary);
                                                }else{
                                                    loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                                                    loadLog.setLogMsg("数据加载失败");
                                                }
                                                taskExecuteLogService.update(loadLog);
                                            } catch (ServiceException e) {
                                                load_logger.error("比较发送接收条数失败，查询DataRecvLog失败", e);
                                            }
                                            exec.shutdown();
                                        }else{
                                            load_logger.warn("数据文件["+uncFile.getAbsolutePath()+"]正在解析中，暂不删除");
                                        }
                                    }
                                },loadLogid));
                            } catch (Exception e) {
                                load_logger.error("解析文件异常:",e);
                                load_logger.info("[recvTask]更新t_birs_exch_data_log表id:" + loadLogid+",状态为：" + StaticCode.EXCH_DATA_STATUS.ERROR.getCode());
                                //更新交换日志状态信息
//                                updateExchDataLog(exchData.getId(), StaticCode.EXCH_DATA_STATUS.ERROR.getCode());
                                //解析完成，通知
                                load_logger.info("[recvTask]回调通知修改表id:" + loadLogid+",状态：" + CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                            }

                        }
                    };
                    exec.submit(run);
                }
            }catch(Exception e){
                String msg = "数据加载失败";
                logger.error("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],服务器异常:文件接收失败,"+e);
                loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());//数据接收失败
                taskExecuteLogDao.update(loadLog);
            }
            while (true) {
                if (exec.isTerminated()) {
                    break;
                }
                Thread.sleep(200);
            }
            return loadResult(loadLogid);
        } catch (Exception e) {
            logger.error("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],服务器异常:文件接收失败,"+e);
        }
        return null;
    }
    public Result loadResult(String loadLogId){
        Result result = new Result();
        try {
            TaskExecuteLog loadLog = taskExecuteLogDao.get(loadLogId);
            result.setLinkLogId(loadLog.getId());
            result.setTaskLogId(loadLog.getGroupId());
            if (loadLog.getLogStatus() == null || loadLog.getLogStatus().equalsIgnoreCase(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus()) || loadLog.getLogStatus().equalsIgnoreCase("")) {
                loadLog.setLogStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                loadLog.setLogMsg("数据加载失败");
                taskExecuteLogDao.update(loadLog);
                result.setStatus(CommonStaticCode.SUCCESSFAIL.FAIL.getStatus());
                result.setMsg("数据加载失败");
            }else{
                result.setStatus(CommonStaticCode.SUCCESSFAIL.SUCCESS.getStatus());
                result.setMsg("数据加载成功");
            }
        } catch (DaoException e) {
            load_logger.error("数据加载失败",e);
        }
        return result;
    }
    public void execute(DataSourceVo dataSourceVo, ChangeVo changeVo, String loadLogId,String databaseSystime){

        logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],开始解析changeSqlVo{"+count(changeVo)+"}");

        //当insert语句转换成update语句需要的信息
        Map<String,ConvertInfo> convertMap = new HashMap<String,ConvertInfo>();
        Map<String,Object> infoMap=new HashMap<String, Object>();//数据解析信息
        Set<String> relatedTable=new HashSet<String>();//所涉及到的表

        List<Map<String,List<Object[]>>> sqllist = convert(changeVo, convertMap,relatedTable,databaseSystime);
        try {

            int num=0;
            for (Map<String, List<Object[]>> map : sqllist) {
                Set<String> set=map.keySet();
                for (String key : set) {
                    int t=map.get(key).size();
                    num=num+t;
                }
            }
            logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],解析结束changeSqlVo，统计出来的sql共有["+num+"]条");
            TaskExecuteLog loadLog = taskExecuteLogDao.get(loadLogId);
            //
            infoMap.put("id", changeVo.getId());//解析的标示
            infoMap.put("over", changeVo.isOver());//解析是否结束
            infoMap.put("convertMap", convertMap);//insert 转换成update信息
            infoMap.put("task_log_id", loadLog.getGroupId());
            logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],开始执行sql语句.");
            executeChangeDbDataImpl.doInSingleTransationCircleByParam("",dataSourceVo, sqllist,infoMap,loadLog.getId());
            logger.info("当前线程id["+Thread.currentThread().getId()+"-"+Thread.currentThread().getName()+"],执行sql语句结束.");
        } catch (Exception e) {
            logger.error("批量执行sql语句异常", e);
        }

    }

    /**
     * 格式化成insert sql语句
     * @param map 表的信息
     * @return
     */
    private Map<String,List<Object[]>> formatInsertSql(Map<String, List<RowPro>> map, Map<String, ConvertInfo> convertMap, Set<String> relatedTable ,String databaseSystime){
        if (map!=null) {
            Set<String> tables = map.keySet();
            Map<String,List<Object[]>> tMap=new LinkedHashMap<String, List<Object[]>>();//表的对应信息
            for (String tablename : tables) {
                relatedTable.add(tablename);//存储所涉及到的表
                //构造sql语句
                StringBuilder insertsb = new StringBuilder();
                insertsb.append("insert into ").append(tablename).append(" (");

                StringBuilder updatesb = new StringBuilder();
                //当insert sql语句转换成update sql语句时 对应的update sql语句
                updatesb.append("update ").append(tablename).append(" set ");

                ConvertInfo ci=new ConvertInfo();//insert 转换成update 语句有关的信息
                List<RowPro> list=map.get(tablename);//行对象列表
                List<Object[]> argsList=new ArrayList<Object[]>();

                String[] cols=null;//字段集合
                String[] args;//参数集合
                String[] updateArgs;//update 参数集合
                List<String> nsList=null;//需要使用数据库系统时间的字段
                int argsNum=0;//参数的个数
                for (int i = 0; i < list.size(); i++) {
                    RowPro row=list.get(i);
                    Map<String,ColPro> colsMap=row.getColMap();//字段集合
                    Object[] argValue=new Object[argsNum];//参数值
                    if (i==0) {
                        cols = new String[colsMap.size()];//字段
                        args = new String[colsMap.size()];//参数
                        updateArgs=new String[colsMap.size()];//update sql语句对应的参数
                        colsMap.keySet().toArray(cols);//有序字段
                        nsList = needSystem(colsMap);//需要使用数据库系统时间的字段
                        argsNum = colsMap.size()-nsList.size();//确定参数值的个数
                        argValue=new Object[argsNum];//重置一下参数个数
                        for (int j = 0; j < cols.length; j++) {//遍历有序字段
                            if (nsList.contains(cols[j])) {//如果该字段是系统时间字段
                                args[j] = databaseSystime;
                                updateArgs[j]=cols[j]+" = "+ databaseSystime;
                            }else{//作为参数的字段
                                args[j] = "?";
                                updateArgs[j] = cols[j] + " = ?";
                            }
                        }

                        //拼接sql，拼接成 insert into user(id,name,age) values (?,?,?)的形式
                        insertsb.append(StringUtils.arrayToDelimitedString(cols, ",")).append(")").append(" values (").append(StringUtils.arrayToDelimitedString(args, ",")).append(")");
//                        sql = sql + StringUtils.arrayToDelimitedString(cols, ",")+")"+" values ("+StringUtils.arrayToDelimitedString(args, ",")+")";//sql语句
                        logger.info("生成insert sql语句为：" + insertsb.toString());
                        ci.setInsertSql(insertsb.toString());
                        //拼接sql，拼接成 update user set id=?,name=? where id=?
                        updatesb.append(StringUtils.arrayToDelimitedString(updateArgs, ",")).append(" where ");
//                        updateSql = updateSql + StringUtils.arrayToDelimitedString(updateArgs, ",")+" where ";//update sql语句
                        logger.info("生成update sql语句为：" + updatesb.toString());
                    }
                    int w=0;//参数计数器
                    for (String col : cols) {
                        if (!nsList.contains(col)) {//只取需要参数的字段值 取出对应字段的值作为参数
                            argValue[w] = this.formatValue(colsMap.get(col).getName(), colsMap.get(col).getType(), colsMap.get(col).getValue());//参数值
                            //如果字段为主键，主键在argValue数组中的索引 第一次循环时就拼成了updateSql,以后不需要在拼装update sql
                            if (i == 0) {
                                if ("1".equals(colsMap.get(col).getPk())) {//
                                    if (ci.getIndex() == null) {
                                        //update sql语句
                                        updatesb.append(colsMap.get(col).getName() + " = ?");
                                        List<Integer> indexs = new ArrayList<Integer>();
                                        indexs.add(w);
                                        ci.setIndex(indexs);////主键索引
                                    } else {
                                        //update sql语句
                                        updatesb.append(" and " + colsMap.get(col).getName() + " = ?");
                                        ci.getIndex().add(w);
                                    }
                                }
                            }
                            w++;//计数器加1
                        }
                    }
                    if(i==0){
                        ci.setUpdateSql(updatesb.toString());
                        convertMap.put(insertsb.toString(), ci);//将信息保存起来
                    }
                    argsList.add(argValue);
                }
                tMap.put(insertsb.toString(), argsList);
            }
            return tMap;
        }
        return null;
    }

    /**
     * sql语句的构造
     * @param vo
     * @param tableMap
     * @param type
     * @param schemaName
     * @return
     */
    private List<Map<String,List<Object[]>>> convert(ChangeVo vo, Map<String,ConvertInfo> convertMap, Set<String> relatedTable,String databaseSystime){
        List<Map<String,List<Object[]>>> sqlList=new ArrayList<Map<String,List<Object[]>>>();

        //处理insertTableData
        Map<String,List<RowPro>> map = vo.getTableData();
        Map<String,List<Object[]>> insertMap = this.formatInsertSql(map,convertMap,relatedTable,databaseSystime);//格式化成insert sql
        if (insertMap!=null && !insertMap.isEmpty()) {
            sqlList.add(insertMap);
        }
        return sqlList;
    }


    private void arrayCopy(Object[] oldArr,Object[] newArr){
        for (int i = 0; i < oldArr.length; i++) {
            Object object = oldArr[i];
            newArr[i]=object;
            if (newArr.length==i+1) {
                break;
            }
        }
    }

    /**
     * 判断一行数据中哪些字段需要使用数据库系统时间
     * @return
     */
    private List<String> needSystem(Map<String, ColPro> row){
        if (row==null || row.isEmpty()) {
            return null;
        }
        List<String> nsList = new ArrayList<String>();

        Set<String> cols=row.keySet();
        for (String col : cols) {
            String type=row.get(col).getType();//字段类型
            String value=row.get(col).getValue();//字段的值
            //如果字段类型是时间字段，并且字段的值等于获取数据库系统时间函数的字符串值
            if ((type.toUpperCase().startsWith(ColType.TIMESTAMP.getType()) || type.toUpperCase().startsWith(ColType.DATE.getType()))
                    && value.toUpperCase().equalsIgnoreCase(datebase_system)) {
                nsList.add(col);//需要使用数据库系统时间
            }
        }
        return nsList;
    }

    /**
     * 转换字段值
     * @param name
     * @param type
     * @param value
     * @return
     */
    private Object formatValue(String name, String type, String value){
        if (value==null || "".equals(value)) {//如果value的值为null 或者为""
            return null;
        }
        try {
            return DbTypeConvertUtils.convert(type, value);
        } catch (ParseException e) {
            logger.error("字段["+name+"]转换异常，type["+type+"],name["+name+"]", e);
        }
        return value;
    }
    /**
     * 统计
     * @param changeVo
     * @return
     */
    private String count(ChangeVo changeVo){
        Map<String,List<RowPro>>  map= changeVo.getTableData();
        Set<String> keys=map!=null? map.keySet() :null;
        StringBuilder sb=new StringBuilder();
        if (keys!=null && keys.size()>0) {
            for (String string : keys) {
                sb.append("表").append(string).append("中的需要insert的语句[").append(map.get(string).size()).append("]---");
            }
        }
        return sb.toString();

    }
}
